import 'dart:async';
import 'package:test/test.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart' as sqflite;
import '../entities/bill.dart';
import 'bill_dao.dart';

void main() {
  late sqflite.Database database;
  late BillDao billDao;
  late StreamController<String> changeListener;

  setUpAll(() {
    // 初始化 sqflite_ffi
    sqflite.sqfliteFfiInit();
    sqflite.databaseFactory = sqflite.databaseFactoryFfi;
  });

  setUp(() async {
    database = await sqflite.databaseFactory.openDatabase(':memory:',
        options: sqflite.OpenDatabaseOptions(
            version: 1,
            onCreate: (db, version) async {
              await db.execute('''
            CREATE TABLE bills (
              id INTEGER PRIMARY KEY AUTOINCREMENT,
              bill_no TEXT NOT NULL,
              user_id INTEGER NOT NULL,
              product_id INTEGER NOT NULL,
              quantity INTEGER NOT NULL,
              total_amount REAL NOT NULL,
              status TEXT NOT NULL,
              created_at TEXT,
              paid_at TEXT
            )
          ''');
            }));

    changeListener = StreamController<String>.broadcast();
    billDao = BillDao(database, changeListener);
  });

  tearDown(() async {
    await changeListener.close();
    await database.close();
  });

  group('BillDao 基础操作测试', () {
    test('insert - 插入单个账单', () async {
      final bill = Bill(
        billNo: 'BILL001',
        userId: 1,
        productId: 1,
        quantity: 2,
        totalAmount: 99.99,
        status: 'pending',
        createdAt: DateTime.now(),
      );

      final id = await billDao.insert(bill);
      expect(id, greaterThan(0));
    });

    test('inserts - 批量插入账单', () async {
      final bills = [
        Bill(
          billNo: 'BILL002',
          userId: 1,
          productId: 1,
          quantity: 1,
          totalAmount: 49.99,
          status: 'pending',
          createdAt: DateTime.now(),
        ),
        Bill(
          billNo: 'BILL003',
          userId: 2,
          productId: 2,
          quantity: 3,
          totalAmount: 149.97,
          status: 'pending',
          createdAt: DateTime.now(),
        ),
      ];

      final ids = await billDao.inserts(bills);
      expect(ids.length, equals(2));
      expect(ids.every((id) => id > 0), isTrue);
    });

    test('findById - 根据ID查找账单', () async {
      final bill = Bill(
        billNo: 'BILL004',
        userId: 1,
        productId: 1,
        quantity: 1,
        totalAmount: 29.99,
        status: 'pending',
        createdAt: DateTime.now(),
      );

      final id = await billDao.insert(bill);
      final foundBill = await billDao.findById(id);

      expect(foundBill, isNotNull);
      expect(foundBill!.billNo, equals('BILL004'));
      expect(foundBill.userId, equals(1));
      expect(foundBill.totalAmount, equals(29.99));
    });

    test('findById - 查找不存在的账单', () async {
      final foundBill = await billDao.findById(999);
      expect(foundBill, isNull);
    });

    test('exists - 检查账单是否存在', () async {
      final bill = Bill(
        billNo: 'BILL005',
        userId: 1,
        productId: 1,
        quantity: 1,
        totalAmount: 19.99,
        status: 'pending',
        createdAt: DateTime.now(),
      );

      final id = await billDao.insert(bill);
      final exists = await billDao.exists(id);
      final notExists = await billDao.exists(999);

      expect(exists, isTrue);
      expect(notExists, isFalse);
    });

    test('update - 更新账单', () async {
      final bill = Bill(
        billNo: 'BILL006',
        userId: 1,
        productId: 1,
        quantity: 1,
        totalAmount: 39.99,
        status: 'pending',
        createdAt: DateTime.now(),
      );

      final id = await billDao.insert(bill);
      final updatedBill = bill.copyWith(
        id: id,
        status: 'paid',
        paidAt: DateTime.now(),
      );

      await billDao.update(updatedBill);
      final foundBill = await billDao.findById(id);

      expect(foundBill!.status, equals('paid'));
      expect(foundBill.paidAt, isNotNull);
    });

    test('delete - 删除账单', () async {
      final bill = Bill(
        billNo: 'BILL007',
        userId: 1,
        productId: 1,
        quantity: 1,
        totalAmount: 59.99,
        status: 'pending',
        createdAt: DateTime.now(),
      );

      final id = await billDao.insert(bill);
      final billWithId = bill.copyWith(id: id);

      final deletedRows = await billDao.delete(billWithId);
      expect(deletedRows, equals(1));

      final foundBill = await billDao.findById(id);
      expect(foundBill, isNull);
    });

    test('deleteById - 根据ID删除账单', () async {
      final bill = Bill(
        billNo: 'BILL008',
        userId: 1,
        productId: 1,
        quantity: 1,
        totalAmount: 69.99,
        status: 'pending',
        createdAt: DateTime.now(),
      );

      final id = await billDao.insert(bill);
      await billDao.deleteById(id);

      final foundBill = await billDao.findById(id);
      expect(foundBill, isNull);
    });

    test('findAll - 查找所有账单', () async {
      final bills = [
        Bill(
          billNo: 'BILL009',
          userId: 1,
          productId: 1,
          quantity: 1,
          totalAmount: 29.99,
          status: 'pending',
          createdAt: DateTime.now(),
        ),
        Bill(
          billNo: 'BILL010',
          userId: 2,
          productId: 2,
          quantity: 2,
          totalAmount: 59.98,
          status: 'paid',
          createdAt: DateTime.now(),
        ),
      ];

      await billDao.inserts(bills);
      final allBills = await billDao.findAll();

      expect(allBills.length, greaterThanOrEqualTo(2));
      expect(allBills.any((b) => b.billNo == 'BILL009'), isTrue);
      expect(allBills.any((b) => b.billNo == 'BILL010'), isTrue);
    });

    test('updates - 批量更新账单', () async {
      final bills = [
        Bill(
          billNo: 'BILL011',
          userId: 1,
          productId: 1,
          quantity: 1,
          totalAmount: 19.99,
          status: 'pending',
          createdAt: DateTime.now(),
        ),
        Bill(
          billNo: 'BILL012',
          userId: 2,
          productId: 2,
          quantity: 1,
          totalAmount: 29.99,
          status: 'pending',
          createdAt: DateTime.now(),
        ),
      ];

      final ids = await billDao.inserts(bills);
      final updatedBills = [
        bills[0].copyWith(id: ids[0], status: 'paid'),
        bills[1].copyWith(id: ids[1], status: 'cancelled'),
      ];

      await billDao.updates(updatedBills);

      final foundBill1 = await billDao.findById(ids[0]);
      final foundBill2 = await billDao.findById(ids[1]);

      expect(foundBill1!.status, equals('paid'));
      expect(foundBill2!.status, equals('cancelled'));
    });

    test('deletes - 批量删除账单', () async {
      final bills = [
        Bill(
          billNo: 'BILL013',
          userId: 1,
          productId: 1,
          quantity: 1,
          totalAmount: 19.99,
          status: 'pending',
          createdAt: DateTime.now(),
        ),
        Bill(
          billNo: 'BILL014',
          userId: 2,
          productId: 2,
          quantity: 1,
          totalAmount: 29.99,
          status: 'pending',
          createdAt: DateTime.now(),
        ),
      ];

      final ids = await billDao.inserts(bills);
      final billsWithIds = [
        bills[0].copyWith(id: ids[0]),
        bills[1].copyWith(id: ids[1]),
      ];

      final deletedRows = await billDao.deletes(billsWithIds);
      expect(deletedRows, equals(2));

      final foundBill1 = await billDao.findById(ids[0]);
      final foundBill2 = await billDao.findById(ids[1]);

      expect(foundBill1, isNull);
      expect(foundBill2, isNull);
    });
  });
}
